import { getCurrentInstance, nextTick, provide, inject, ComponentInternalInstance } from "vue";
import { I18nInjectionKey } from "vue-i18n";
import dataSourceMap from "./dataSourceMap";
import { useRouter, useRoute } from "vue-router";
import { getGlobalProperties } from "@/app";
import * as utils from "@/utils"
import { toggleTheme } from "@/theme";

const AppSymbol = Symbol("AppSymbol")


export const lowcodeWrap = (props: any, context: any) => {

    const global: any = { };
    const instance = getCurrentInstance() as ComponentInternalInstance;
    const { t, locale }: any = inject(I18nInjectionKey)?.global;
    const router = useRouter();
    const route = useRoute();
    const ref = (ref: any) => instance?.refs[ref],
        setState = async (newState: any, callback: any) => {
            Object.assign(global.state, newState);
            await nextTick(() => callback?.apply(global));
        },
        getLocale = () => locale.value,
        setLocale = (val: any) => {
            locale.value = val;
        },
        location = () => window.location,
        history = () => window.history;


    Object.defineProperties(global, {
        props: { get: () => props },
        emit: { get: () => context.emit },
        setState: { get: () => setState },
        appStore: { get: () => inject(AppSymbol) },
        i18n: { get: () => t },
        getLocale: { get: () => getLocale },
        setLocale: { get: () => setLocale },
        reload: { get: async () => {
                await router.push({
                    name: 'reload',
                })
            }
        },
        location: { get: location },
        history: { get: history },
        utils: { get: ()=> utils },
        dataSourceMap: { get: () => dataSourceMap },
        router: { get: () => router },
        route: { get: () => route },
        config: { get: () => getGlobalProperties() },
        toggleTheme: { get: () => toggleTheme },
        $: { get: () => ref }
    });

    const wrap = (fn: any) => {
        if (typeof fn === "function") {
            return (...args: any) => fn.apply(global, args);
        }

        Object.entries(fn).forEach(([name, value]) => {
            Object.defineProperty(global, name, {
                get: () => value,
            });
        });

        fn.t = t;

        return fn;
    };

    return wrap;
};

export default () => {
    const i18n: any = inject(I18nInjectionKey);

    provide(I18nInjectionKey, i18n);

    const stores = {
        app: inject(AppSymbol),
    };

    return { t: i18n.global.t, stores, lowcodeWrap };
};
